package com.my.collection.stack.v15;

import java.util.concurrent.locks.AbstractQueuedSynchronizer;

/**
 * Created by Scarlett on 2018/7/27 0027.
 */
public class ReentrantLock {
    private final Sync sync;

    public ReentrantLock() {
        this.sync = new Sync();
    }


    public void lock() {
        this.sync.acquire(1);
    }

    public void unlock() {
        this.sync.release(1);
    }

    private static class Sync extends AbstractQueuedSynchronizer {

        @Override
        protected boolean tryAcquire(int arg) {
            if (arg <= 0) {
                throw new IllegalArgumentException();
            }

            if (getState() == 0) {
                if (compareAndSetState(0, arg)) {
                    setExclusiveOwnerThread(Thread.currentThread());
                    return true;
                }
            } else {
                if (getExclusiveOwnerThread() == Thread.currentThread()) {
                    int state = getState() + arg;
                    return compareAndSetState(getState(), state);
                }
            }

            return false;
        }

        @Override
        protected boolean tryRelease(int arg) {
            if (arg <= 0) {
                throw new IllegalArgumentException();
            }

            if (getState() > 0) {
                int state = getState() - arg;
                if (compareAndSetState(getState(), state)) {
                    return true;
                }
            }

            setState(0);
            setExclusiveOwnerThread(null);
            return true;
        }

    }

}
